package com.desay.pangoo.itmt.controller;

import java.io.IOException;
import java.util.*;

import javax.servlet.http.HttpServletResponse;

import com.desay.pangoo.itmt.service.TechProcessService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.desay.pangoo.common.lite.lang.web.BusinessException;
import com.desay.pangoo.common.lite.lang.web.CommonResponse;
import com.desay.pangoo.common.lite.lang.web.CustomException;
import com.desay.pangoo.itmt.constants.Constant;
import com.desay.pangoo.itmt.constants.TechProjectInfoFileds;
import com.desay.pangoo.itmt.controller.vo.TechProjectInfoChangeVo;
import com.desay.pangoo.itmt.controller.vo.TechProjectInfoEntityVo;
import com.desay.pangoo.itmt.controller.vo.TechProjectInfoVo;
import com.desay.pangoo.itmt.entity.*;
import com.desay.pangoo.itmt.enums.ExceptionCodeEnum;
import com.desay.pangoo.itmt.feign.ProjectRequestService;
import com.desay.pangoo.itmt.repository.BUDivRepository;
import com.desay.pangoo.itmt.repository.ProjectBURepository;
import com.desay.pangoo.itmt.repository.TechProjectInfoRepository;
import com.desay.pangoo.itmt.repository.TechRefProjectRepository;
import com.desay.pangoo.itmt.repository.spec.ExpandCriteria;
import com.desay.pangoo.itmt.repository.spec.Restrictions;
import com.desay.pangoo.itmt.service.TechProjectInfoService;
import com.desay.pangoo.itmt.utils.ExportUtil;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.http.HtmlUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import com.desay.pangoo.itmt.config.TechProjectSchedule;

/**
 * 数据集
 *
 * @author uidq1163
 */
@RestController
@Api(tags = "ITMT Tech Project Info管理")
@RequestMapping(value = "/techProjectInfo")
@Validated
@Slf4j
public class TechProjectInfoController {

	public static final String MATURITYFILED = "maturity";

	public static final String RESOURCENEEDEDFILED = "resourceNeeded";

	public static final String KEYTECFILED = "KeyTec";
	@Autowired
	private TechProjectInfoService techProjectInfoService;
	@Autowired
	private TechProcessService techProcessService;

	@Autowired
	private TechProjectSchedule techProjectSchedule;

	@PostMapping
	@ApiOperation(value = "添加工作组分类项目信息", notes = "添加工作组分类项目信息")
	public ResponseEntity<Object> create(@Validated @RequestBody TechProjectInfoVo vo) {
		return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.create(vo)), HttpStatus.OK);
	}

	@PostMapping(value = "change")
	@ApiOperation(value = "课题变更申请", notes = "课题变更申请")
	public ResponseEntity<Object> projectChange(@RequestBody TechProjectInfoChangeVo vo) {
		return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.projectChange(vo)), HttpStatus.OK);
	}

	@GetMapping(value = "change")
	@ApiOperation(value = "获取项目信息变更申请列表", notes = "获取项目信息变更申请列表")
	@ApiImplicitParams({ @ApiImplicitParam(name = "pageNo", type = "int", value = "指定查询页数", paramType = "query"),
			@ApiImplicitParam(name = "pageSize", type = "int", value = "每页数据数量", paramType = "query"),
			@ApiImplicitParam(name = "auditStatus", type = "int", value = "审核状态：1待审核，2审核通过，3审核不通过", paramType = "query"),
			@ApiImplicitParam(name = "techClassId", value = "技术分类ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "workGroupId", value = "工作组分类ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "techId", value = "技术主键ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "applyId", value = "主键ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "techName", value = "技术名称(模糊查询)", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "techPtn", value = "技术编号(模糊查询)", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "auditor", value = "审核人员（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "creator", value = "申请提出者（模糊查询）", dataTypeClass = String.class, paramType = "query"), })
	public ResponseEntity<Object> getAllChangeList(
			@RequestParam(value = "workGroupId", required = false) Long workGroupId,
			@RequestParam(value = "techId", required = false) Long techId,
			@RequestParam(value = "applyId", required = false) Long applyId,
			@RequestParam(value = "techPtn", required = false) String techPtn,
			@RequestParam(value = "techName", required = false) String techName,
			@RequestParam(value = "creator", required = false) String creator,
			@RequestParam(value = "auditor", required = false) String auditor,
			@RequestParam(value = "techClassId", required = false) Long techClassId,
			@RequestParam(value = "auditStatus", required = false) Integer auditStatus,
			@RequestParam(value = "pageNo", required = true, defaultValue = "1") Integer pageNo,
			@RequestParam(value = "pageSize", required = true, defaultValue = "10") Integer pageSize) {
		return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.getChangeList(applyId,techId, pageSize,
				pageNo, techClassId, workGroupId, techPtn, techName, creator, auditor, auditStatus)), HttpStatus.OK);
	}

	@PostMapping(value = "change/audit/{id}")
	@ApiOperation(value = "课题变更申请审核", notes = "课题变更申请审核")
	public ResponseEntity<Object> projectChangeAudit(@RequestBody TechProjectInfoChangeVo vo,
			@PathVariable(value = "id") Long id) {
		techProjectInfoService.auditProjectChange(vo, id);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@DeleteMapping(value = "{id}")
	@ApiOperation(value = "删除", notes = "删除工作组分类项目信息")
	@ApiImplicitParam(name = "id", value = "工作组ID", required = true, dataTypeClass = Long.class, paramType = "path")
	public ResponseEntity<Object> delete(@PathVariable long id) {
		techProjectInfoService.delete(id);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@PutMapping(value = "{id}")
	@ApiOperation(value = "更新工作组分类项目信息", notes = "更新工作组分类项目信息")
	public ResponseEntity<Object> update(@PathVariable(value = "id") Long id,
			@Validated @RequestBody TechProjectInfoVo vo) {
		techProjectInfoService.update(id, vo);
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@GetMapping(value = "{id}")
	@ApiOperation(value = "根据id获取工作组分类项目信息", notes = "根据id获取工作组分类项目信息")
	public ResponseEntity<Object> getById(@PathVariable(value = "id") Long id) {
		return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.getById(id)), HttpStatus.OK);
	}

	@GetMapping(value = "history/{id}")
	@ApiOperation(value = "根据id获取课题历史信息", notes = "根据id获取课题历史信息")
	@ApiImplicitParams({ @ApiImplicitParam(name = "pageNo", type = "int", value = "指定查询页数", paramType = "query"),
			@ApiImplicitParam(name = "pageSize", type = "int", value = "每页数据数量", paramType = "query") })
	public ResponseEntity<Object> getHistoryById(@PathVariable(value = "id") Long id,
			@RequestParam(value = "pageNo", required = true, defaultValue = "1") Integer pageNo,
			@RequestParam(value = "pageSize", required = true, defaultValue = "10") Integer pageSize) {
		return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.getHistoryById(pageSize, pageNo, id)),
				HttpStatus.OK);
	}

	@GetMapping
	@ApiOperation(value = "获取工作组分类项目信息列表", notes = "获取工作组分类项目信息列表")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "year", value = "技术规划年", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "pageNo", type = "int", value = "指定查询页数", paramType = "query"),
			@ApiImplicitParam(name = "pageSize", type = "int", value = "每页数据数量", paramType = "query"),
			@ApiImplicitParam(name = "techClassId", value = "技术分类ID", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "workGroupId", value = "工作组分类ID", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "techPtn", value = "技术编号(模糊查询)", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "researchForms", value = "研究形式", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "techName", value = "技术名称（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "subsidiary", value = "子技术（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "description", value = "描述（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "techLevel", value = "技术等级", dataTypeClass = Integer.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "priority", value = "优先级", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "quantitativeIndicators", value = "量化指标（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "tMTApproval", value = "TMT评审", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = MATURITYFILED, value = "技术状态", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "requirementSource", value = "需求来源", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "developedBy", value = "开发负责人（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "relevanceBuss", value = "相关BU（调整后字段）", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "dutyBuss", value = "开发责任主体", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "platforms", value = "产品平台", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "toolsEquipment", value = "设备需求（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "minResourceNeeded", value = "资源需求（大于）", dataTypeClass = Float.class, paramType = "query"),
			@ApiImplicitParam(name = "maxResourceNeeded", value = "资源需求（小于）", dataTypeClass = Float.class, paramType = "query"),
			@ApiImplicitParam(name = "status", value = "状态：1:plan 2:on ", dataTypeClass = Integer.class, paramType = "query"),
			@ApiImplicitParam(name = "deliveryReview", value = "技术交付评审结果（Success，Failure，BU's NEEDS，-）", allowMultiple = true, dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "isAll", value = "是否取所有数据：true,false:近五年的数据", required = false, dataType = "bool", allowableValues = "true,false", paramType = "query"),
			@ApiImplicitParam(name = "isMajorProject", value = "重点项目", required = false, dataType = "bool", allowableValues = "true,false", paramType = "query") })
	public ResponseEntity<Object> getAllList(@RequestParam(value = "year", required = false) List<Long> year,
			@RequestParam(value = "workGroupId", required = false) List<Long> workGroupId,
			@RequestParam(value = "techPtn", required = false) String techPtn,
			@RequestParam(value = "researchForms", required = false) List<String> researchForms,
			@RequestParam(value = "techName", required = false) String techName,
			@RequestParam(value = "subsidiary", required = false) String subsidiary,
			@RequestParam(value = "description", required = false) String description,
			@RequestParam(value = "techLevel", required = false) List<Integer> techLevel,
			@RequestParam(value = "priority", required = false) List<String> priority,
			@RequestParam(value = "quantitativeIndicators", required = false) String quantitativeIndicators,
			@RequestParam(value = "tMTApproval", required = false) List<String> tMTApproval,
			@RequestParam(value = MATURITYFILED, required = false) List<String> maturity,
			@RequestParam(value = "deliveryReview", required = false) List<String> deliveryReview,
			@RequestParam(value = "requirementSource", required = false) List<String> requirementSource,
			@RequestParam(value = "developedBy", required = false) String developedBy,
			@RequestParam(value = "relevanceBuss", required = false) List<Long> relevanceBuss,
			@RequestParam(value = "dutyBuss", required = false) List<Long> dutyBuss,
			@RequestParam(value = "toolsEquipment", required = false) String toolsEquipment,
			@RequestParam(value = "minResourceNeeded", required = false) Float minResourceNeeded,
			@RequestParam(value = "maxResourceNeeded", required = false) Float maxResourceNeeded,
			@RequestParam(value = "techClassId", required = false) List<Long> techClassId,
			@RequestParam(value = "platforms", required = false) List<Long> platforms,
			@RequestParam(value = "status", required = false) Integer status,
			@RequestParam(value = "isAll", required = true, defaultValue = "0") Boolean isAll,
			@RequestParam(value = "isMajorProject", required = false) Boolean isMajorProject,
			@RequestParam(value = "pageNo", required = true, defaultValue = "1") Integer pageNo,
			@RequestParam(value = "pageSize", required = true, defaultValue = "10") Integer pageSize) {
		return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.getList(pageSize, pageNo, techClassId,
				workGroupId, techPtn, researchForms, techName, subsidiary, description, techLevel, priority,
				quantitativeIndicators, tMTApproval, maturity, requirementSource, developedBy, relevanceBuss, dutyBuss,
				toolsEquipment, minResourceNeeded, maxResourceNeeded, isAll, platforms, year, deliveryReview, status,
				isMajorProject)), HttpStatus.OK);
	}

	@PostMapping(value = "/file/excel")
	@ApiOperation(value = "文件上传")
	public ResponseEntity<Object> uploadExcel(MultipartFile multipartFile) {
		try {
			return new ResponseEntity<>(CommonResponse.success(techProjectInfoService.uploadExcelFile(multipartFile)),
					HttpStatus.OK);
		} catch (CustomException e) {
			// 业务异常直接抛出去
			throw e;
		} catch (IOException e) {
			throw new BusinessException(ExceptionCodeEnum.UPLOAD_FILE_ERROR);
		}
	}

	@Autowired
	TechProjectInfoRepository techProjectInfoRepository;

	@GetMapping(value = "/download", headers = "Accept=application/octet-stream")
	@ApiOperation(value = "文件导出", notes = "文件导出")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "year", value = "技术规划年", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "techClassId", value = "技术分类ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "workGroupId", value = "工作组分类ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "techPtn", value = "技术编号(模糊查询)", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "researchForms", value = "研究形式", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "techName", value = "技术名称（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "subsidiary", value = "子技术（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "description", value = "描述（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "techLevel", value = "技术等级", dataTypeClass = Integer.class, paramType = "query"),
			@ApiImplicitParam(name = "priority", value = "优先级", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "quantitativeIndicators", value = "量化指标（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "tMTApproval", value = "TMT评审", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = MATURITYFILED, value = "技术状态", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "requirementSource", value = "需求来源", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "developedBy", value = "开发负责人（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "toolsEquipment", value = "设备需求（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "minResourceNeeded", value = "资源需求（大于）", dataTypeClass = Float.class, paramType = "query"),
			@ApiImplicitParam(name = "maxResourceNeeded", value = "资源需求（小于）", dataTypeClass = Float.class, paramType = "query"),
			@ApiImplicitParam(name = "workGroupId", value = "工作组分类ID", dataTypeClass = Long.class, paramType = "query"),
			@ApiImplicitParam(name = "isAll", value = "是否取所有数据：true,false:近五年的数据", required = false, dataType = "bool", allowableValues = "true,false", paramType = "query"),
			@ApiImplicitParam(name = "isMajorProject", value = "是否重点项目", required = false, dataType = "bool", allowableValues = "true,false", paramType = "query"), })
	public void download(@RequestParam(value = "year", required = false) Long year,
			@RequestParam(value = "workGroupId", required = false) Long workGroupId,
			@RequestParam(value = "techPtn", required = false) String techPtn,
			@RequestParam(value = "researchForms", required = false) String researchForms,
			@RequestParam(value = "techName", required = false) String techName,
			@RequestParam(value = "subsidiary", required = false) String subsidiary,
			@RequestParam(value = "description", required = false) String description,
			@RequestParam(value = "techLevel", required = false) Integer techLevel,
			@RequestParam(value = "priority", required = false) String priority,
			@RequestParam(value = "quantitativeIndicators", required = false) String quantitativeIndicators,
			@RequestParam(value = "tMTApproval", required = false) String tMTApproval,
			@RequestParam(value = MATURITYFILED, required = false) String maturity,
			@RequestParam(value = "requirementSource", required = false) String requirementSource,
			@RequestParam(value = "developedBy", required = false) String developedBy,
			@RequestParam(value = "toolsEquipment", required = false) String toolsEquipment,
			@RequestParam(value = "minResourceNeeded", required = false) Float minResourceNeeded,
			@RequestParam(value = "maxResourceNeeded", required = false) Float maxResourceNeeded,
			@RequestParam(value = "techClassId", required = false) Long techClassId,
			@RequestParam(value = "isMajorProject", required = false) Boolean isMajorProject,
			@RequestParam(value = "isAll", required = true, defaultValue = "0") Boolean isAll,
			HttpServletResponse response) throws IOException {
		ExpandCriteria<TechProjectInfoEntity> c = new ExpandCriteria<>();
		// 根据组查询
		c.add(Restrictions.eq("techClass.id", techClassId, true));

		c.add(Restrictions.eq("techClass.workGroup.id", workGroupId, true));
		// 技术编号：techPtn
		c.add(Restrictions.like("techPtn", techPtn, true));
		// 研究形式
		c.add(Restrictions.eq("researchForms", researchForms, true));
		// 技术名称
		c.add(Restrictions.like("techName", techName, true));
		// 子技术
		c.add(Restrictions.like("subsidiary", subsidiary, true));
		// 说明
		c.add(Restrictions.like("description", description, true));
		// 技术等级
		c.add(Restrictions.eq("techLevel", techLevel, true));
		// 重点项目
		c.add(Restrictions.eq("isMajorProject", isMajorProject, true));
		// 优先级
		c.add(Restrictions.eq(TechProjectInfoFileds.PRIORITY, priority, true));
		// 量化指标
		c.add(Restrictions.like("quantitativeIndicators", quantitativeIndicators, true));
		// TMT 评审
		c.add(Restrictions.eq("tMTApproval", tMTApproval, true));
		// 技术状态
		c.add(Restrictions.eq(MATURITYFILED, maturity, true));
		// 需求来源
		c.add(Restrictions.eq("requirementSource", requirementSource, true));
		// 开发负责人
		c.add(Restrictions.like("developedBy", developedBy, true));
		// 设备需求
		c.add(Restrictions.like("toolsEquipment", toolsEquipment, true));
		// 资源需求(人月）
		c.add(Restrictions.gte(RESOURCENEEDEDFILED, minResourceNeeded, true));
		c.add(Restrictions.lte(RESOURCENEEDEDFILED, maxResourceNeeded, true));
		if (Boolean.FALSE.equals(isAll)) {
			// 取近五年的数据
			List<Long> ids = techProjectInfoRepository.getLately5YearsPprojectIds();
			c.add(Restrictions.in("id", ids, true));
		}
		ExportUtil<TechProjectInfoEntity> exportUtil = new ExportUtil<>(techProjectInfoRepository, c);
		exportUtil.export("技术课题导出", response, this::process);
	}

	/**
	 * 指定表头信息和内容
	 *
	 * @param objMap
	 * @return
	 */
	private Map<String, Object> process(TechProjectInfoEntity objMap) {
		Map<String, Object> row = new LinkedHashMap<>();

		row.put("creator", objMap.getCreator());
		row.put("createTime", objMap.getCreateTime());
		row.put("workGroup", objMap.getTechClass().getWorkGroup().getWorkGroupName());
		// Classification
		row.put("Classification", objMap.getTechClass().getClassificationName());
		// PTN
		row.put("PTN", objMap.getTechPtn());
		// Research forms
		row.put("Research forms", objMap.getResearchForms());
		// Technology name
		try {
			JSONObject jSONObject = JSON.parseObject(objMap.getTechName());
			if (null != jSONObject && jSONObject.containsKey(Constant.JSON_STR)
					&& null != jSONObject.getString(Constant.JSON_STR)) {
				String techName = HtmlUtil.cleanHtmlTag(jSONObject.getString(Constant.JSON_STR));
				row.put("Technology name", techName);
			} else {
				row.put("Technology name", objMap.getTechName());
			}
		} catch (Exception e) {
			row.put("Technology name", objMap.getTechName());
		}
		// Subsidiary
		row.put("Subsidiary", objMap.getSubsidiary());
		// Description
		try {
			JSONObject descriptionObject = JSON.parseObject(objMap.getDescription());
			if (null != descriptionObject && descriptionObject.containsKey(Constant.JSON_STR)
					&& null != descriptionObject.getString(Constant.JSON_STR)) {
				String description = HtmlUtil.cleanHtmlTag(descriptionObject.getString(Constant.JSON_STR));
				row.put("Description", description);
			} else {
				row.put("Description", objMap.getDescription());
			}
		} catch (Exception e) {
			row.put("Description", objMap.getDescription());
		}
		// KeyTec
		// 技术等级:核心:1，关键:2，通用:3，一般:4'
		switch (objMap.getTechLevel()) {
		case 1:
			row.put(KEYTECFILED, "核心技术");
			break;
		case 2:
			row.put(KEYTECFILED, "关键技术");
			break;
		case 3:
			row.put(KEYTECFILED, "通用技术");
			break;
		case 4:
			row.put(KEYTECFILED, "一般技术");
			break;
		default:
			row.put(KEYTECFILED, "");
		}

		// priority
		row.put(TechProjectInfoFileds.PRIORITY, objMap.getPriority());

		for (int i = 2021; i < 2030; i++) {
			for (int j = 1; j <= 4; j++) {
				row.put(i + "Q" + j, "");
			}
		}
		for (TechYearQuarterEntity year : objMap.getTechYearQuarters()) {
			if (year.getStatus() == 1) {
				row.put(year.getYear() + "Q" + year.getQuarter(), "PLAN");
			} else {
				row.put(year.getYear() + "Q" + year.getQuarter(), "ON");
			}
		}
		// Quantitative indicators
		JSONObject quantitativeObject;
		try {
			quantitativeObject = JSON.parseObject(objMap.getQuantitativeIndicators());
			if (null != quantitativeObject && quantitativeObject.containsKey(Constant.JSON_STR)
					&& null != quantitativeObject.getString(Constant.JSON_STR)) {
				String quantitative = HtmlUtil.cleanHtmlTag(quantitativeObject.getString(Constant.JSON_STR));
				row.put("Quantitative indicators", quantitative);
			} else {
				row.put("Quantitative indicators", objMap.getQuantitativeIndicators());
			}
		} catch (Exception e) {
			row.put("Quantitative indicators", objMap.getQuantitativeIndicators());
		}

		// TMT Approval
		row.put("TMT Approval", objMap.getTMTApproval());
		// 技术状态
		row.put("Technical state", objMap.getMaturity());
		// 技术成熟度
		row.put(MATURITYFILED, objMap.getTechMaturity());
		// 是否重点项目
		row.put("Is Major Project", objMap.getIsMajorProject() == null ? "" : objMap.getIsMajorProject() ? "是" : "否");
		// 技术交付评审
		row.put("Delivery Review", objMap.getDeliveryReview());

		// Requirement Source
		row.put("Requirement Source", objMap.getRequirementSource());
		// Developed By
		row.put("Developed By", objMap.getDevelopedBy());
		// Tools and Equipment
		row.put("Tools and Equipment", objMap.getToolsEquipment());
		// Resource Needed
		row.put("Resource Needed", objMap.getResourceNeeded());
		// 预算，不包含（人力）
		row.put("Budgeting Not Include Human", objMap.getPlanBudgeting());
		// 总预算
		row.put("Budgeting", objMap.getBudgeting());
		// 相关BU
		if (CollUtil.isNotEmpty(objMap.getRelevanceBuss())) {
			row.put("Relevant Bu", objMap.getRelevanceBuss().stream().map(r -> r.getBu()).toList());
		} else {
			row.put("Relevant Bu", "");
		}
		// 开发责任主体
		if (CollUtil.isNotEmpty(objMap.getDutyBuss())) {
			row.put("Subject of development responsibility",
					objMap.getDutyBuss().stream().map(r -> r.getBu()).toList());
		} else {
			row.put("Subject of development responsibility", "");
		}
		// 产品平台
		if (CollUtil.isNotEmpty(objMap.getPlatforms())) {
			row.put("Product Platform", objMap.getPlatforms().stream().map(r -> r.getProductPlatform()).toList());
		} else {
			row.put("Product Platform", "");
		}
		// 項目信息
		if (null != objMap.getProject()) {
			row.put("ProjectNo", objMap.getProject().getProjectNo());
			row.put("ProjectName", objMap.getProject().getProjectName());
			row.put("ProjectResult", objMap.getProject().getProjectResult());
			row.put("ApprovalDate", objMap.getProject().getApprovalDate());
			row.put("ActualClosedDate", objMap.getProject().getActualClosedDate());
			row.put("EstimateClosedDate", objMap.getProject().getEstimateClosedDate());
		} else {
			row.put("ProjectNo", "");
			row.put("ProjectName", "");
			row.put("ProjectResult", "");
			row.put("ApprovalDate", "");
			row.put("ActualClosedDate", "");
			row.put("EstimateClosedDate", "");
		}
		// 专利信息
		if (null != objMap.getPatent()) {
			row.put("PatentCode", objMap.getPatent().getPatentCode());
			row.put("PatentNum", objMap.getPatent().getPatentNum());
			row.put("PatentStatus", objMap.getPatent().getPatentStatus());
		} else {
			row.put("PatentCode", "");
			row.put("PatentNum", "");
			row.put("PatentStatus", "");
		}
		// ALM需求编号
		row.put("AlmCode", objMap.getAlmCode());
		return row;
	}

	@GetMapping(value = "technicalShelf")
	@ApiOperation(value = "技术货架", notes = "技术货架")
	public ResponseEntity<Object> getAllList() {
		ExpandCriteria<TechProjectInfoEntity> c = new ExpandCriteria<>();
		c.add(Restrictions.eq(MATURITYFILED, "released", true));
		List<TechProjectInfoEntity> list = techProjectInfoRepository.findAll(c);
		List<?> result = list.stream().map(t -> {
			TechProjectInfoEntityVo vo = new TechProjectInfoEntityVo();
			BeanUtils.copyProperties(t, vo);
			return vo;
		}).toList();
		return new ResponseEntity<>(CommonResponse.success(result), HttpStatus.OK);
	}

	@GetMapping(value = "technicalRoad")
	@ApiOperation(value = "技术路标", notes = "技术路标")
	public ResponseEntity<Object> getTechnicalRoadList() {
		ExpandCriteria<TechProjectInfoEntity> c = new ExpandCriteria<>();
		c.add(Restrictions.in(MATURITYFILED,
				Arrays.asList(
						new String[] { "developing", "tmt approved", "project approved", "planning", "proposal" }),
				true));
		List<TechProjectInfoEntity> list = techProjectInfoRepository.findAll(c);
		List<?> result = list.stream().map(t -> {
			TechProjectInfoEntityVo vo = new TechProjectInfoEntityVo();
			BeanUtils.copyProperties(t, vo);
			return vo;
		}).toList();
		return new ResponseEntity<>(CommonResponse.success(result), HttpStatus.OK);
	}

	@GetMapping(value = "technicalAnalysis")
	@ApiOperation(value = "技术价值分析", notes = "技术价值分析")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "year", value = "技术规划年", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "techClassId", value = "技术分类ID", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "workGroupId", value = "工作组分类ID", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "techPtn", value = "技术编号(模糊查询)", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "researchForms", value = "研究形式", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "techName", value = "技术名称（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "subsidiary", value = "子技术（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "description", value = "描述（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "techLevel", value = "技术等级", dataTypeClass = Integer.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "priority", value = "优先级", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "quantitativeIndicators", value = "量化指标（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "tMTApproval", value = "TMT评审", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = MATURITYFILED, value = "技术状态", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "requirementSource", value = "需求来源", dataTypeClass = String.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "developedBy", value = "开发负责人（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "relevanceBuss", value = "相关BU（调整后字段）", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "dutyBuss", value = "开发责任主体", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "platforms", value = "产品平台", dataTypeClass = Long.class, allowMultiple = true, paramType = "query"),
			@ApiImplicitParam(name = "toolsEquipment", value = "设备需求（模糊查询）", dataTypeClass = String.class, paramType = "query"),
			@ApiImplicitParam(name = "minResourceNeeded", value = "资源需求（大于）", dataTypeClass = Float.class, paramType = "query"),
			@ApiImplicitParam(name = "maxResourceNeeded", value = "资源需求（小于）", dataTypeClass = Float.class, paramType = "query"),
			@ApiImplicitParam(name = "isAll", value = "是否取所有数据：true,false:近五年的数据", required = false, dataType = "bool", allowableValues = "true,false", paramType = "query"), })
	public ResponseEntity<Object> getTechnicalAnalysisList(
			@RequestParam(value = "year", required = false) List<Long> years,
			@RequestParam(value = "workGroupId", required = false) List<Long> workGroupId,
			@RequestParam(value = "techPtn", required = false) String techPtn,
			@RequestParam(value = "researchForms", required = false) List<String> researchForms,
			@RequestParam(value = "techName", required = false) String techName,
			@RequestParam(value = "subsidiary", required = false) String subsidiary,
			@RequestParam(value = "description", required = false) String description,
			@RequestParam(value = "techLevel", required = false) List<Integer> techLevel,
			@RequestParam(value = "priority", required = false) List<String> priority,
			@RequestParam(value = "quantitativeIndicators", required = false) String quantitativeIndicators,
			@RequestParam(value = "tMTApproval", required = false) List<String> tMTApproval,
			@RequestParam(value = MATURITYFILED, required = false) List<String> maturity,
			@RequestParam(value = "requirementSource", required = false) List<String> requirementSource,
			@RequestParam(value = "developedBy", required = false) String developedBy,
			@RequestParam(value = "relevanceBuss", required = false) List<Long> relevanceBuss,
			@RequestParam(value = "dutyBuss", required = false) List<Long> dutyBuss,
			@RequestParam(value = "toolsEquipment", required = false) String toolsEquipment,
			@RequestParam(value = "minResourceNeeded", required = false) Float minResourceNeeded,
			@RequestParam(value = "maxResourceNeeded", required = false) Float maxResourceNeeded,
			@RequestParam(value = "techClassId", required = false) List<Long> techClassId,
			@RequestParam(value = "platforms", required = false) List<Long> platforms,
			@RequestParam(value = "isAll", required = true, defaultValue = "0") Boolean isAll) {
		ExpandCriteria<TechProjectInfoEntity> c = new ExpandCriteria<>();
		c.add(Restrictions.ne(MATURITYFILED, "CANCELLED", true));

		// 年
		c.add(Restrictions.in("techYearQuarters.year", years, true));
		// 根据组查询
		c.add(Restrictions.in("techClass.id", techClassId, true));

		c.add(Restrictions.in("techClass.workGroup.id", workGroupId, true));
		// 技术编号：techPtn
		c.add(Restrictions.like(TechProjectInfoFileds.TECHPTN, techPtn, true));
		// 研究形式
		c.add(Restrictions.in("researchForms", researchForms, true));
		// 技术名称
		c.add(Restrictions.like(TechProjectInfoFileds.TECHNAME, techName, true));
		// 子技术
		c.add(Restrictions.like(TechProjectInfoFileds.SUBSIDIARY, subsidiary, true));
		// 说明
		c.add(Restrictions.like("description", description, true));
		// 技术等级
		c.add(Restrictions.in("techLevel", techLevel, true));
		// 优先级
		c.add(Restrictions.in(TechProjectInfoFileds.PRIORITY, priority, true));
		// 量化指标
		c.add(Restrictions.like("quantitativeIndicators", quantitativeIndicators, true));
		// TMT 评审
		c.add(Restrictions.in("tMTApproval", tMTApproval, true));
		// 技术状态
		c.add(Restrictions.in(TechProjectInfoFileds.MATURITY, maturity, true));
		// 需求来源
		c.add(Restrictions.in("requirementSource", requirementSource, true));
		// 开发负责人
		c.add(Restrictions.like("developedBy", developedBy, true));
		// 相关BU（调整后字段）
		c.add(Restrictions.in("relevanceBuss.id", relevanceBuss, true));
		// 开发责任主体
		c.add(Restrictions.in("dutyBuss.id", dutyBuss, true));
		// 产品平台
		c.add(Restrictions.in("platforms.id", platforms, true));
		// 设备需求
		c.add(Restrictions.like("toolsEquipment", toolsEquipment, true));
		// 资源需求(人月）
		c.add(Restrictions.gte(TechProjectInfoFileds.RESOURCENEEDED, minResourceNeeded, true));
		c.add(Restrictions.lte(TechProjectInfoFileds.RESOURCENEEDED, maxResourceNeeded, true));
		if (Boolean.FALSE.equals(isAll)) {
			// 取近五年的数据
			List<Long> ids = techProjectInfoRepository.getLately5YearsPprojectIds();
			c.add(Restrictions.in("id", ids, true));
		}
		List<TechProjectInfoEntity> list = techProjectInfoRepository.findAll(c);
		List<?> result = list.stream().map(t -> {
			TechProjectInfoEntityVo vo = new TechProjectInfoEntityVo();
			BeanUtils.copyProperties(t, vo);
			return vo;
		}).toList();
		return new ResponseEntity<>(CommonResponse.success(result), HttpStatus.OK);
	}

	@Autowired
	ProjectBURepository projectBURepository;
	@Autowired
	BUDivRepository bUDivRepository;

	@PostMapping(value = "/file/project/excel")
	@ApiOperation(value = "文件上传：平台-BU关联关系")
	public void uploadProjectBUExcel(MultipartFile multipartFile) {
		try {
			ExcelReader reader = ExcelUtil.getReader(multipartFile.getInputStream());
			List<String> sheetNames = reader.getSheetNames();
			reader = ExcelUtil.getReader(multipartFile.getInputStream(), sheetNames.get(0));
			List<Map<String, Object>> datas = reader.readAll();
			for (Map<String, Object> map : datas) {
				String project = (String) map.get("Project");
				if (null == project) {
					continue;
				}

				ProjectBUEntity bu = projectBURepository.findByProductPlatform(project);
				if (null == bu) {
					bu = new ProjectBUEntity();
				}
				String bus = map.get("BU").toString();
				String[] busArray = bus.split(",");
				Set<BUDivEntity> busSets = new HashSet<>();
				for (String buName : busArray) {
					BUDivEntity buEntity = bUDivRepository.findByBu(buName);
					if (null != buEntity) {
						busSets.add(buEntity);
					}
				}
				bu.setBus(busSets);
				bu.setProductPlatform((String) map.get("Project"));
				bu.setPlatform((String) map.get("Platform"));
				projectBURepository.save(bu);
			}
		} catch (CustomException e) {
			// 业务异常直接抛出去
			throw e;
		} catch (IOException e) {
			throw new BusinessException(ExceptionCodeEnum.UPLOAD_FILE_ERROR);
		}
	}

	@PostMapping(value = "/file/bu/excel")
	@ApiOperation(value = "文件上传:BU-DIV对应关系")
	public void uploadBUExcel(MultipartFile multipartFile) {
		try {
			ExcelReader reader = ExcelUtil.getReader(multipartFile.getInputStream());
			List<String> sheetNames = reader.getSheetNames();
			reader = ExcelUtil.getReader(multipartFile.getInputStream(), sheetNames.get(0));
			List<Map<String, Object>> datas = reader.readAll();
			for (Map<String, Object> map : datas) {
				String bu = (String) map.get("BU");
				if (null == bu) {
					continue;
				}
				BUDivEntity buEntity = bUDivRepository.findByBu(bu);
				if (null == buEntity) {
					buEntity = new BUDivEntity();
				}
				buEntity.setBu(map.get("BU").toString());
				buEntity.setDivName((String) map.get("Div"));
				bUDivRepository.save(buEntity);
			}
		} catch (CustomException e) {
			// 业务异常直接抛出去
			throw e;
		} catch (IOException e) {
			throw new BusinessException(ExceptionCodeEnum.UPLOAD_FILE_ERROR);
		}
	}

	@PostMapping(value = "/file/budgeting/excel")
	@ApiOperation(value = "文件上传:导入价值信息")
	public void uploadBudgetingExcel(MultipartFile multipartFile) {
		try {
			ExcelReader reader = ExcelUtil.getReader(multipartFile.getInputStream());
			List<String> sheetNames = reader.getSheetNames();
			reader = ExcelUtil.getReader(multipartFile.getInputStream(), sheetNames.get(0));
			List<Map<String, Object>> datas = reader.readAll();
			for (Map<String, Object> map : datas) {
				String ptn = (String) map.get("PTN");
				if (null == ptn) {
					continue;
				}
				TechProjectInfoEntity entity = techProjectInfoRepository.findByTechPtn(ptn);
				if (null == entity) {
					continue;
				}
				if (null != map.get("budgeting") && !"TBD".equals(map.get("budgeting").toString())) {
					entity.setPlanBudgeting(Float.valueOf(map.get("budgeting").toString()));
				}
				if (null != map.get("human_budgeting") && !"TBD".equals(map.get("human_budgeting").toString())) {
					entity.setHumanBudgeting(Float.valueOf(map.get("human_budgeting").toString()));
				}
				if (null != map.get("total") && StringUtils.isNotEmpty(map.get("total").toString())) {
					entity.setBudgeting(Float.valueOf(map.get("total").toString()));
				}
				String platform = map.get("platform").toString();
				Set<ProjectBUEntity> platformsEntity = new HashSet<>();
				if (StringUtils.isNotEmpty(platform)) {
					String[] platforms = platform.split(",");
					for (String name : platforms) {
						ProjectBUEntity bu = projectBURepository.findByProductPlatform(name);
						if (null != bu) {
							platformsEntity.add(bu);
						}
					}
					entity.setPlatforms(platformsEntity);
				}
				techProjectInfoRepository.save(entity);
			}
		} catch (CustomException e) {
			// 业务异常直接抛出去
			throw e;
		} catch (IOException e) {
			throw new BusinessException(ExceptionCodeEnum.UPLOAD_FILE_ERROR);
		}
	}

	@GetMapping(value = "setTechnicalCost")
	@ApiOperation(value = "课题费用重置", notes = "课题费用重置")
	public ResponseEntity<Object> setTechnicalCost() {
		ExpandCriteria<TechProjectInfoEntity> c = new ExpandCriteria<>();
		List<TechProjectInfoEntity> list = techProjectInfoRepository.findAll(c);
		list.stream().forEach(t -> {
			// budgeting 总预算
			// planBudgeting 课题规划费用预算
			// resourceNeeded 资源需求(人月）
			t.setBudgeting((null == t.getPlanBudgeting() ? 0 : t.getPlanBudgeting())
					+ 40000 * (null == t.getResourceNeeded() ? 0 : t.getResourceNeeded()));
			techProjectInfoRepository.save(t);
		});
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	@Autowired
	private ProjectRequestService projectRequestService;
	@Autowired
	TechRefProjectRepository techRefProjectRepository;

	@PostMapping(value = "/file/project/techMaturity")
	@ApiOperation(value = "文件上传：成熟度与技术项目编号")
	public void uploadProjectTechMaturityExcel(MultipartFile multipartFile) {
		try {
			ExcelReader reader = ExcelUtil.getReader(multipartFile.getInputStream());
			List<String> sheetNames = reader.getSheetNames();
			reader = ExcelUtil.getReader(multipartFile.getInputStream(), sheetNames.get(0));
			List<Map<String, Object>> datas = reader.readAll();
			for (Map<String, Object> map : datas) {
				String ptn = (String) map.get("ptn");
				String techMaturity = (String) map.get("techMaturity");
				String projectName = (String) map.get("projectName");
				TechProjectInfoEntity entity = techProjectInfoRepository.findByTechPtn(ptn);
				if (null != entity) {
					if (StringUtils.isNotEmpty(techMaturity)) {
						entity.setTechMaturity(techMaturity);
					}
					ProjectEntity project = entity.getProject();
					if (null == entity.getProject()) {
						project = new ProjectEntity();
					} else {
						project.setProjectName(projectName);
						entity.setProject(project);
						continue;
					}
					/// systemSetting/projects/name
					if (StringUtils.isNotEmpty(projectName)) {
						ResponseEntity<HashMap<String, String>> response = projectRequestService
								.getProjectInfo(projectName);
						HashMap<String, String> projectDto = response.getBody();
						if (null == projectDto) {
							log.error("项目信息不存在--{}", projectName);
						} else {
							project.setProjectName(projectName);
							// 【项目编号】
							project.setProjectNo(projectDto.get("almProjectId"));
							// 【项目结果】
							project.setProjectResult(projectDto.get("finalResult"));
							// 【立项时间】
							project.setApprovalDate(projectDto.get("actualStartDate"));
							// 【实际结项时间】
							project.setActualClosedDate(projectDto.get("actualSOPDate"));
							// 【预计结项时间】
							project.setEstimateClosedDate(projectDto.get("planSOPDate"));
							entity.setProject(project);
						}
					}
					techProjectInfoRepository.save(entity);
				}
			}
		} catch (CustomException e) {
			// 业务异常直接抛出去
			throw e;
		} catch (IOException e) {
			throw new BusinessException(ExceptionCodeEnum.UPLOAD_FILE_ERROR);
		}
	}

	@PutMapping(value = "/test")
	@ApiOperation(value = "手动同步项目信息到系统")
	public void test() {
		techProjectSchedule.updateTrinityProject();
	}

	@DeleteMapping(value = "/techInfo/{id}")
	@ApiOperation(value = "删除课题信息")
	public ResponseEntity<Object> deleteTechInfo(@PathVariable("id") Long id) {
		Optional<TechProjectInfoEntity> techProjectInfo = techProjectInfoRepository.findById(id);
		if (techProjectInfo.isPresent()) {
			techProjectInfo.get().remove();
			techProjectInfoRepository.delete(techProjectInfo.get());
		}
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}

	/***
	 * ptn列表转换成ID
	 */
	@PostMapping(value = "/convertPtnToIds")
	@ApiOperation(value = "ptn列表转换成ID")
	public ResponseEntity<Object> convertPtnToIds(@RequestBody List<String> ptns) {
		// 返回ptn和id的集合
		// 根据ptn查询id
		List<TechProjectInfoEntity> techProjectInfoEntities = techProjectInfoRepository.findAllByTechPtnIn(ptns);
		Map<String, Object> map = new HashMap<>();
		techProjectInfoEntities.stream().forEach(t -> map.put(t.getTechPtn(), t.getId()));
		return new ResponseEntity<>(CommonResponse.success(map), HttpStatus.OK);
	}

	/**
	 * 获取技术流程相关信息
	 */
	@GetMapping(value = "/techProcess/{techProcessId}")
	@ApiOperation(value = "获取技术流程相关信息")
	public ResponseEntity<Object> getTechProcess(@PathVariable("techProcessId") Long techProcessId) {
		return new ResponseEntity<>(CommonResponse.success(techProcessService.getTechProcess(techProcessId)),
				HttpStatus.OK);
	}

	@GetMapping(value = "/sendTechProjectInfoToAi")
	@ApiOperation(value = "检查是否有必填字段没有填写")
	public ResponseEntity<Object> checkRequiredField() {
		techProjectSchedule.sendTechProjectInfoToAi();
		return new ResponseEntity<>(CommonResponse.success(), HttpStatus.OK);
	}
}
